<template>
  <div class='d-field d-selectfield' :class="{ 'validate-error': hintType === 'error', required: isRequired, 'd-field-hashint': !hideHint }">
    <label :style="{ width: labelWidth != null ? labelWidth + 'px' : '' }" v-show="!hideLabel">{{ labelText }}</label>
    <div class="d-field-content" :style="{ marginLeft: labelWidth != null ? labelWidth + 'px' : '' }">
      <div @click="toggleSelect($event)" class="d-selectfield-box" :class="{ active: selectVisible }" :style="{ width: realEditorWidth ? realEditorWidth : '' }">
        <input class="d-selectfield-box-text" @keydown="handleKeydown" @input="handleInput" v-model="searchText" /><span class="d-selectfield-trigger d-icon d-icon-arrow-down"></span>
        <d-select v-ref:select v-if="selectActive" v-show="selectVisible" :multi-select="multiSelect" :value.sync="selectValue" @select="selectVisible = false" @selection-change="handleSelectionChange" @click="$event.stopPropagation()">
          <d-option v-for="(key, val) in mapping" :value="val" :show-checkbox="multiSelect">{{ key }}</d-option>
        </d-select>
      </div>
      <div class="d-field-hint" v-if="!hideHint">
        <i class='d-icon' :class="{ 'd-icon-error': hintType === 'error', 'd-icon-warning': hintType === 'warning' }"></i>{{hintMessage || '' }}
      </div>
    </div>
  </div>
</template>

<style>
  .d-selectfield {
  }

  .d-selectfield .d-select {
    position: absolute;
    top: 32px;
    max-height: 200px;
    z-index: 1;
    background: #fff;
    width: 100%;
    left: 0;
    box-sizing: border-box;
  }

  .d-selectfield-box {
    position: relative;
    cursor: pointer;
    font-size: 14px;
    padding-left: 4px;
    border: 1px solid #e5e6e7;
    background-color: #fff;
    width: 100%;
    padding-right: 24px;
    box-sizing: border-box;
    border-radius: 2px;
    line-height: 28px;
    height: 28px;
    transition: border 0.3s;
  }

  .d-selectfield-box.active {
    border-color: #1ab394;
  }

  .d-selectfield-box .d-selectfield-trigger {
    position: absolute;
    top: 0;
    right: 0;
    margin-right: 4px;
  }

  .d-selectfield-box-text {
    display: inline-block;
    overflow: hidden;
    width: 100%;
    line-height: 24px;
    vertical-align: top;
    border: none;
    outline: none;
  }
</style>

<script type="text/ecmascript-6">
  import { merge, getPath, setPath } from '../../util';
  import { default as common } from './field-common';
  import { default as Dropdown } from '../../service/dropdown';

  const FUNCTION_KEYS = [13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40];

  export default {
    props: merge({
      multiSelect: {
        type: Boolean,
        default: false
      },

      emptyRecord: {
        type: Boolean,
        default: false
      },

      editable: {
        type: Boolean,
        default: false
      }
    }, common.props),

    data() {
      return {
        searchModel: '',
        selectActive: false,
        selectVisible: false
      };
    },

    computed: merge({
      textValue() {
        const mapping = this.mapping;
        const selectValue = this.selectValue;

        const reversedMap = {};

        for (var label in mapping) {
          if (mapping.hasOwnProperty(label)) {
            var value = mapping[label];
            reversedMap[value] = label;
          }
        }

        if (selectValue instanceof Array) {
          return selectValue.map(function(item) {
            return reversedMap[item];
          }).join(',');
        }

        if (mapping && selectValue !== null && selectValue !== undefined) {
          return reversedMap[selectValue];
        }
      },

      searchText: {
        get() {
          if (!this.selectVisible) {
            return this.textValue;
          }
          return this.searchModel;
        },
        set(newValue) {
          this.searchModel = newValue;
        }
      },

      selectValue: {
        get() {
          if (this.model && this.property) {
            return getPath(this.model, this.property);
          }
        },
        set(newValue) {
          if (this.model && this.property) {
            setPath(this.model, this.property, newValue);
          }
        }
      }
    }, common.computed),

    components: {
      DSelect: require('../select.vue'),
      DOption: require('../select-option.vue')
    },

    events: common.events,

    created: common.onCreated,

    destroyed: common.onDestroyed,

    compiled: common.onCompiled,

    watch: {
      selectVisible(newVal) {
        if (newVal === true) {
          Dropdown.open(this);
        } else {
          Dropdown.close(this);
        }
      }
    },

    methods: merge({
      onDocumentClick() {
        this.selectVisible = false;
      },

      handleKeydown(event) {
        var keyCode = event.keyCode;
        if (!this.editable && FUNCTION_KEYS.indexOf(keyCode) === -1) {
          event.preventDefault();
        }

        if (keyCode === 27) {
          this.selectVisible = false;
        }
      },

      handleInput() {
        this.fetchMapping(this.searchModel);
      },

      handleSelectionChange() {
        const children = this.$refs.select.$children;
        const value = [];

        children.forEach(function(child) {
          if (child.selected) {
            value.push(child.value);
          }
        });
        this.selectValue = value;
      },

      toggleSelect() {
        this.selectActive = true;
        this.selectVisible = !this.selectVisible;
      },

      showSelect() {
        this.selectActive = true;
        this.selectVisible = true;
      },

      hideSelect() {
        this.selectVisible = false;
      }
    }, common.methods)
  };
</script>